package com.moyz.adi.common.service;

import com.moyz.adi.common.cosntant.AdiConstant;
import com.moyz.adi.common.entity.AiModel;
import com.moyz.adi.common.exception.BaseException;
import com.moyz.adi.common.interfaces.AbstractLLMService;
import com.moyz.adi.common.interfaces.TriConsumer;
import com.moyz.adi.common.util.DashscopeUtil;
import com.moyz.adi.common.vo.*;
import dev.langchain4j.data.image.Image;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.model.dashscope.QwenChatModel;
import dev.langchain4j.model.dashscope.QwenStreamingChatModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.Collections;
import java.util.List;

import static com.moyz.adi.common.enums.ErrorEnum.B_LLM_SECRET_KEY_NOT_SET;

/**
 * 灵积模型服务(DashScope LLM service)。
 * <p>
 * 该类继承自 {@link AbstractLLMService} 并实现了特定于 DashScope 平台的语言模型服务，
 * 提供了初始化、配置和使用 DashScope API 的具体实现。
 */
@Slf4j
public class DashScopeLLMService extends AbstractLLMService<DashScopeSetting> {

    /**
     * 构造函数，用于初始化 DashScope 模型服务。
     *
     * @param aiModel AI 模型实例
     */
    public DashScopeLLMService(AiModel aiModel) {
        super(aiModel, AdiConstant.SysConfigKey.DASHSCOPE_SETTING, DashScopeSetting.class);
    }

    /**
     * 检测该服务是否可用（不可用的情况通常是没有配置 key 或者模型未启用）。
     *
     * @return 如果服务可用则返回 true，否则返回 false
     */
    @Override
    public boolean isEnabled() {
        return StringUtils.isNotBlank(modelPlatformSetting.getApiKey()) && aiModel.getIsEnable();
    }

    /**
     * 在聊天之前进行参数检查。
     * <p>
     * 特别地，对于多模态 LLM（例如支持图片输入的模型），如果未接收到图片，则会记录警告信息。
     *
     * @param params 聊天请求参数
     * @return 如果检查通过则返回 true
     */
    @Override
    protected boolean checkBeforeChat(SseAskParams params) {
        if (CollectionUtils.isEmpty(params.getAssistantChatParams().getImageUrls())
                && DashscopeUtil.vlChatModelNameProvider().anyMatch(item -> item.equalsIgnoreCase(params.getModelName()))) {
            log.warn("多模态LLM没有接收到图片,modelName:{}", params.getModelName());
        }
        return true;
    }

    /**
     * 实现具体的 ChatLanguageModel 构建逻辑。
     *
     * @param properties LLM 构建属性
     * @return 构建好的 ChatLanguageModel 实例
     */
    @Override
    protected ChatLanguageModel doBuildChatLLM(LLMBuilderProperties properties) {
        // 检查 API Key 是否设置
        if (StringUtils.isBlank(modelPlatformSetting.getApiKey())) {
            throw new BaseException(B_LLM_SECRET_KEY_NOT_SET);
        }

        // 设置默认温度值，并根据属性覆盖
        float temperature = 0.7f;
        if (properties != null && properties.getTemperature() > 0 && properties.getTemperature() <= 1) {
            temperature = properties.getTemperature().floatValue();
        }

        // 使用 QwenChatModel 构建 ChatLanguageModel
        return QwenChatModel.builder()
                .apiKey(modelPlatformSetting.getApiKey())
                .temperature(temperature)
                .modelName(aiModel.getName())
                .build();
    }

    /**
     * 构建一个 StreamingChatLanguageModel 实例。
     *
     * @param properties LLM 构建属性
     * @return 构建好的 StreamingChatLanguageModel 实例
     */
    @Override
    public StreamingChatLanguageModel buildStreamingChatLLM(LLMBuilderProperties properties) {
        // 检查 API Key 是否设置
        if (StringUtils.isBlank(modelPlatformSetting.getApiKey())) {
            throw new BaseException(B_LLM_SECRET_KEY_NOT_SET);
        }

        // 设置默认温度值，并根据属性覆盖
        float temperature = 0.7f;
        if (properties != null && properties.getTemperature() > 0 && properties.getTemperature() <= 1) {
            temperature = properties.getTemperature().floatValue();
        }

        // 使用 QwenStreamingChatModel 构建 StreamingChatLanguageModel
        return QwenStreamingChatModel.builder()
                .apiKey(modelPlatformSetting.getApiKey())
                .modelName(aiModel.getName())
                .temperature(temperature)
                .build();
    }

    /**
     * 解析来自 API 的错误响应并转换为自定义异常。
     * <p>
     * 注意：当前实现中此方法返回 null，可能需要根据实际需求进行扩展。
     *
     * @param error 错误对象
     * @return 解析后的 LLMException 异常，当前实现总是返回 null
     */
    @Override
    protected LLMException parseError(Object error) {
        // 当前实现中此方法返回 null，可能需要根据实际需求进行扩展
        return null;
    }

}
